#include "i2c_touch_screen.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"

static const char* TAG = "touch_screen_driver";
uint16_t _tsXResolution;
uint16_t _tsYResolution;
i2c_master_dev_handle_t dev_handle;
bool _tsFlag;

void i2c_master_init(void) {
    i2c_master_bus_config_t conf = {
        .clk_source = I2C_CLK_SRC_DEFAULT,
        .i2c_port = I2C_NUM_0,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .glitch_ignore_cnt = 7,
        .flags.enable_internal_pullup = true,
    };
    i2c_master_bus_handle_t ret_bus_handle;
    i2c_new_master_bus(&conf, &ret_bus_handle);
    i2c_device_config_t dev_cfg = {
        .dev_addr_length = I2C_ADDR_BIT_LEN_7,
        .device_address = TOUCH_SCREEN_I2C_ADDR,
        .scl_speed_hz = 100000,
    };

    i2c_master_bus_add_device(ret_bus_handle, &dev_cfg, &dev_handle);
}

esp_err_t i2c_master_read_slave(uint8_t addr, uint8_t* data, size_t len) {
    esp_err_t ret;
    ret = i2c_master_receive(dev_handle, data, len, -1);
    return ret;
}

void touch_screen_get_resolution(uint16_t *xRes, uint16_t *yRes){
    const uint8_t cmd_x[] = {0x53, 0x60, 0x00, 0x00}; // Get x resolution
    const uint8_t cmd_y[] = {0x53, 0x63, 0x00, 0x00}; // Get y resolution
    uint8_t rec[4];
    i2c_master_transmit_receive(dev_handle, cmd_x, sizeof(cmd_x), rec, sizeof(rec), -1);
    *xRes = ((rec[2])) | ((rec[3] & 0xf0) << 4);
    i2c_master_transmit_receive(dev_handle, cmd_y, sizeof(cmd_x), rec, sizeof(rec), -1);
    *yRes = ((rec[2])) | ((rec[3] & 0xf0) << 4);
    _tsFlag = false;
}
/*esp_err_t i2c_master_write_slave(uint8_t addr, uint8_t reg, uint8_t* data, size_t len) {
    esp_err_t ret;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, true);
    i2c_master_write_byte(cmd, reg, true);
    i2c_master_write(cmd, data, len, true);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
}*/

static void IRAM_ATTR tsInt(void* arg) {
    // 中断处理代码，例如读取触摸屏数据
    ESP_LOGI("TS_INT", "Interrupt triggered!");
    /*uint8_t touch_data[8];
    if (touch_screen_read(touch_data, sizeof(touch_data)) == ESP_OK) {
        ESP_LOGI(
            "Main",
            "Touch data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
            touch_data[0],
            touch_data[1],
            touch_data[2],
            touch_data[3],
            touch_data[4],
            touch_data[5],
            touch_data[6],
            touch_data[7]
        );
    } else {
        ESP_LOGE("Main", "Failed to read touch data");
    }*/
   _tsFlag = true;
}

void touch_screen_init(void) {
    i2c_master_init();

    gpio_config_t io_conf;
    // 设置为输入模式
    io_conf.mode = GPIO_MODE_INPUT;
    // 位掩码，选择TS_INT引脚
    io_conf.pin_bit_mask = (1ULL << I2C_MASTER_INT_IO);
    // 禁用中断
    io_conf.intr_type = GPIO_INTR_NEGEDGE;
    // 启用上拉电阻
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
    // 应用配置
    gpio_config(&io_conf);

    // 使能下降沿中断
    gpio_set_intr_type(I2C_MASTER_INT_IO, GPIO_INTR_NEGEDGE);
    // 配置中断
    gpio_install_isr_service(ESP_INTR_FLAG_EDGE);

    gpio_isr_handler_add(I2C_MASTER_INT_IO, tsInt, NULL);
    touch_screen_get_resolution(&_tsXResolution,&_tsYResolution);

    _tsFlag = false;

}
void ts_get_xy(uint8_t *_d, uint16_t *x, uint16_t *y)
{
    *x = *y = 0;
    *x = (_d[0] & 0xf0);
    *x <<= 4;
    *x |= _d[1];
    *y = (_d[0] & 0x0f);
    *y <<= 8;
    *y |= _d[2];
}
uint8_t touch_screen_read(uint16_t *xPos, uint16_t *yPos) {
    uint8_t fingers = 0;
    uint8_t _raw[8];
    uint16_t xRaw[2], yRaw[2];
    i2c_master_read_slave(TOUCH_SCREEN_I2C_ADDR, _raw, sizeof(_raw));
    for (int i = 0; i < 8; i++)
    {
        if (_raw[7] & (1 << i))
            fingers++;
    }
    for (int i = 0; i < 2; i++)
    {
        ts_get_xy((_raw + 1) + (i * 3), &xRaw[i], &yRaw[i]);

        yPos[i] = 600 - 1 - ((xRaw[i] * 600 - 1) / _tsXResolution);
        xPos[i] = ((yRaw[i] * 600 - 1) / _tsYResolution);
        
    }
    _tsFlag = false;
    return fingers;

}
